﻿using System.Web.Mvc;
using CID.Domain.Operations;
using CID.Tests.Support;
using CID.Web.Controllers;
using CID.Web.Models.Operations;
using NailsFramework.Config;
using NailsFramework.IoC;
using NailsFramework.Persistence;
using NailsFramework.UserInterface.TestingSupport;
using NUnit.Framework;
using Rhino.Mocks;

namespace CID.Web.Tests.Controllers
{
    [TestFixture]
    class AjaxEnabledBaseCRUDControllerTests : BaseWebTests
    {

        private AjaxEnabledControllerStub controller;
        private ServerViewModel viewModel;

        protected override void ConfigureNails(INailsConfigurator nails)
        {
            nails.IoC.Container<NailsFramework.IoC.Unity>()
                 .Persistence.DataMapper<NailsFramework.Persistence.NHibernate>(CID.Domain.Persistence.Configuration.Configure)
                 .UserInterface.Platform<NailsFramework.UserInterface.Mvc>()
                 .Logging.Logger<NailsFramework.Logging.Log4net>()
                 .IoC.Lemming<NailsFramework.UnitOfWork.Session.WebExecutionContext>(x => x.Ignore())
                 .IoC.Lemming<NailsFramework.UnitOfWork.Session.CallExecutionContext>()
                 .InspectAssemblyOf<Server>()
                 .InspectAssemblyOf<ServerController>()
                 .InspectAssemblyOf<AjaxEnabledBaseCRUDControllerTests>()
                 .Initialize();
        }

        public override void SetUp()
        {
            base.SetUp();

            controller = TestControllers.Get<AjaxEnabledControllerStub>();
            var requestContext = StubsBuilder.BuildRequestContextStub();
            controller.ControllerContext = new ControllerContext(requestContext, controller);
            controller.Url = new UrlHelper(requestContext);

            viewModel = ViewModelStubBuilder.BuildViewModelStub<ServerViewModel, IServer>(OperationsData.Server1);
            viewModel.Stub(x => x.UpdateModel(OperationsData.Server1)).IgnoreArguments().Throw(new DomainExceptionStub());
        }

        [Test]
        public void PrepareViewModel_ShouldSetPostUrl()
        {
            controller.DoPrepareViewModelForView(viewModel);
            Assert.AreEqual(controller.Url.RouteUrl(controller.Url.RequestContext.RouteData.Values), viewModel.PostUrl);
        }

        #region Edit
        [Test]
        public void PostEdit_InvalidDataWithNonAjaxRequest_ShouldReturnViewResult()
        {
            var result = controller.Edit(viewModel.Id, viewModel);

            Assert.IsTrue(controller.EditWasCalled);
            Assert.IsFalse(controller.CreateWasCalled);
            Assert.IsInstanceOf<ViewResult>(result);
        }

        [Test]
        public void PostEdit_InvalidDataWithAjaxRequest_ShouldReturnJsonResult()
        {
            StubsBuilder.StubRequestAsAjaxRequest(controller.ControllerContext.RequestContext.HttpContext.Request);
            var result = controller.Edit(viewModel.Id, viewModel);

            Assert.IsTrue(controller.EditWasCalled);
            Assert.IsFalse(controller.CreateWasCalled);
            Assert.IsInstanceOf<JsonResult>(result);
        }
        #endregion

        #region Create
        [Test]
        public void PostCreate_InvalidDataWithNonAjaxRequest_ShouldReturnViewResult()
        {
            viewModel.Id = 0;
            var result = controller.Create(viewModel);

            Assert.IsTrue(controller.CreateWasCalled);
            Assert.IsFalse(controller.EditWasCalled);
            Assert.IsInstanceOf<ViewResult>(result);
        }

        [Test]
        public void PostCreate_InvalidDataWithAjaxRequest_ShouldReturnJsonResult()
        {
            viewModel.Id = 0;
            StubsBuilder.StubRequestAsAjaxRequest(controller.ControllerContext.RequestContext.HttpContext.Request);
            var result = controller.Create(viewModel);

            Assert.IsTrue(controller.CreateWasCalled);
            Assert.IsFalse(controller.EditWasCalled);
            Assert.IsInstanceOf<JsonResult>(result);
        }
        #endregion
    }

    #region Controller stub
    public class AjaxEnabledControllerStub : AjaxEnabledBaseCRUDController<IServer, Server, ServerViewModel>
    {
        public bool CreateWasCalled { get; private set; }
        public bool EditWasCalled { get; private set; }

        [Inject]
        public IBag<Location> Locations { private get; set; }


        protected override Server CreateModel(ServerViewModel viewModel)
        {
            return new Server(viewModel.Name, viewModel.Address, Locations.GetById(viewModel.LocationId));
        }

        public override ActionResult Create(ServerViewModel viewModel)
        {
            CreateWasCalled = true;
            return base.Create(viewModel);
        }

        public override ActionResult Edit(int id, ServerViewModel viewModel)
        {
            EditWasCalled = true;
            return base.Edit(id, viewModel);
        }

        public void DoPrepareViewModelForView(ServerViewModel viewModel)
        {
            PrepareViewModelForView(viewModel);
        }
    }
    #endregion
}
